package api

import (
	"context"
	"encoding/json"
	"fmt"
	"github.com/gofiber/fiber/v2/log"
	"github.com/kadycui/fiber-ci/pkg/cache"
	"github.com/kadycui/fiber-ci/pkg/database"
	"github.com/kadycui/fiber-ci/utils"
	"net/http"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/kadycui/fiber-ci/model"
	"github.com/kadycui/fiber-ci/serialize"
)

// GetChannelById is a function to get a Lu by ID
// @Summary 通过ID获取一个渠道详情
// @Description 通过ID一个渠道详情
// @Tags Channel
// @Accept json
// @Produce json
// @Param id path int true "Channel ID"
// @Success 200 {object} serialize.ResponseHTTP{data=[]model.Channel}
// @Failure 404 {object} serialize.ResponseHTTP{}
// @Failure 503 {object} serialize.ResponseHTTP{}
// @Router /v1/channel/{id} [get]
func GetChannelById(c *fiber.Ctx) error {
	id := c.Params("id")
	db := database.DB
	rdb := cache.RDB

	channel := new(model.Channel)
	if err := db.First(&channel, id).Error; err != nil {
		switch err.Error() {
		case "record not found":
			return c.Status(http.StatusNotFound).JSON(serialize.ResponseHTTP{
				Success: false,
				Message: fmt.Sprintf("Channel with ID %v not found.", id),
				Data:    nil,
			})
		default:
			return c.Status(http.StatusServiceUnavailable).JSON(serialize.ResponseHTTP{
				Success: false,
				Message: err.Error(),
				Data:    nil,
			})

		}
	}

	chs := channel.GetCacheChannel()
	// 存储到 Redis
	err := serialize.SetCache(context.Background(), rdb, id, "channel", chs)
	if err != nil {
		panic(err)
	}

	return c.JSON(serialize.ResponseHTTP{
		Success: true,
		Message: "Success get Channel by ID.",
		Data:    *channel,
	})

}

type PostChannel struct {
	Id int64 `json:"id"`
}

func AssemblyLuSuData(lu model.Lu, su model.Su) map[string]interface{} {
	data := map[string]interface{}{
		"suid":       lu.SuID,
		"id":         lu.ID,
		"master_id":  lu.Mluid,
		"name":       lu.Name,
		"tabId":      lu.TabID,
		"bitflag":    lu.Bitflag,
		"commend":    lu.Commend,
		"status":     lu.Status,
		"createtime": lu.CreateTime.Unix(),
		"ip":         su.Host,
		"port":       su.Port,
		"proxy_ip":   su.ProxyHost,
		"proxy_port": su.ProxyPort,
		"use_proxy":  su.UseProxy,
	}
	return data
}

func AssemblyServerData(gIndex int, channelKey string, group model.Group, tabNameDict map[string]string, wg *sync.WaitGroup) map[string]interface{} {

	defer wg.Done()

	db := database.DB
	var gss []model.GroupsServer
	result := db.Where("group_id = ?", group.ID).Find(&gss)
	if result.Error != nil {
		panic("查询分区失败")
	}

	var lusSlice []int64
	for _, gs := range gss {
		lusSlice = append(lusSlice, gs.ServerID)
	}

	var lus []model.Lu
	result = db.Where("id IN ?", lusSlice).Find(&lus)
	if result.Error != nil {
		panic("failed to query users")
	}

	var dataDict = make(map[string]interface{})
	host := ""
	port := 8888
	parts := strings.Split(*group.LoginURL, ":")
	if len(parts) == 2 {
		host = parts[0]
		num, _ := strconv.ParseInt(parts[1], 10, 64)
		port = int(num)
	}
	if *group.Other == "" {
		dataDict["other"] = map[string]interface{}{}
	} else {
		var otherDict map[string]interface{}
		// 解析 JSON 字符串到 map
		err := json.Unmarshal([]byte(*group.Other), &otherDict)
		if err != nil {
			fmt.Printf("%d Json 解析错误: %v", group.ID, err)
		}

		dataDict["other"] = otherDict
	}
	dataDict["id"] = group.ID
	dataDict["version"] = group.ID
	dataDict["audit_servers"] = group.AuditServers
	dataDict["audit_versions"] = group.AuditVersions
	dataDict["resource_version"] = group.ResourceVersion
	dataDict["cdn"] = group.CdnURL
	dataDict["login"] = map[string]interface{}{
		"host": host,
		"port": port,
	}
	dataDict["card"] = group.CardURL
	dataDict["custom"] = group.CustomURL

	jsonGroupData, err := json.Marshal(dataDict)
	if err != nil {
		log.Fatal(err)
	}

	var md5Dict map[string]interface{}
	err = json.Unmarshal(jsonGroupData, &md5Dict)
	if err != nil {
		log.Fatal(err)
	}

	var tabDict = make(map[string][]map[string]interface{})
	for _, lu := range lus {
		var su model.Su
		db.First(&su, lu.SuID)

		channelLuDict := AssemblyLuSuData(lu, su)

		dk := strconv.FormatInt(channelLuDict["tabId"].(int64), 10)
		// 检查 tabID 是否存在于 tabDict 中，不存在则创建一个空列表
		if _, ok := tabDict[dk]; !ok {
			tabDict[dk] = make([]map[string]interface{}, 0)
			tabDict[dk] = append(tabDict[dk], channelLuDict)
		} else {
			// 将 channel_lu_dict 添加到 tabDict 中对应的列表中
			tabDict[dk] = append(tabDict[dk], channelLuDict)
		}
	}

	index := 1
	for key, value := range tabDict {
		k := key
		strIndex := strconv.Itoa(index)
		dataDict[strIndex] = make(map[string]interface{})
		if val, ok := dataDict[strconv.Itoa(index)].(map[string]interface{}); ok {
			// 修改子 map 中的逻辑值
			val["logic"] = value
			val["tabName"] = tabNameDict[k]

			// 将修改后的子 map 存回 dataDict
			dataDict[strconv.Itoa(index)] = val
		} else {
			jsonData, err := json.Marshal(dataDict[strIndex])
			if err != nil {
				fmt.Println("Error marshaling JSON:", err)
			}
			// 打印JSON字符串
			fmt.Printf("%s\n", jsonData)
			fmt.Printf("Key %s not found or value is not of expected type", k)
		}
		index++
	}

	jsonServerData, err := json.Marshal(dataDict)
	if err != nil {
		fmt.Println("Error:", err)
	}

	err = utils.WriteFile("server", channelKey, jsonServerData)
	if err != nil {
		fmt.Println(err.Error())
	}

	md5Sign := utils.Md5(jsonServerData)
	md5Dict["server"] = md5Sign
	jsonMd5rData, err := json.Marshal(md5Dict)
	if err != nil {
		fmt.Println("Error:", err)
	}
	err = utils.WriteFile("md5", channelKey, jsonMd5rData)
	if err != nil {
		fmt.Println(err.Error())
	}

	fmt.Printf("goroutine-%d执行完成, 文件名%s.json\n", gIndex, channelKey)

	return dataDict
}

// CreateChannelJson is a function to Create channel by ID
// @Summary 通过ID生成一个渠道的JSON文件
// @Description 通过ID生成一个渠道的JSON文件
// @Tags Channel
// @Accept json
// @Produce json
// @Param channel_id body PostChannel true "PostChannel"
// @Success 200 {object} serialize.ResponseHTTP{}
// @Failure 404 {object} serialize.ResponseHTTP{}
// @Failure 503 {object} serialize.ResponseHTTP{}
// @Router /v1/channel/createjson [post]
func CreateChannelJson(c *fiber.Ctx) error {
	// 617 kw669hy_android_wei4
	startTime := time.Now()
	db := database.DB
	//rdb := cache.RDB
	pc := new(PostChannel)
	if err := c.BodyParser(&pc); err != nil {
		return c.Status(http.StatusBadRequest).JSON(serialize.ResponseHTTP{
			Success: false,
			Message: err.Error(),
			Data:    nil,
		})
	}

	channel := new(model.Channel)
	if err := db.First(&channel, pc.Id).Error; err != nil {
		switch err.Error() {
		case "record not found":
			return c.Status(http.StatusNotFound).JSON(serialize.ResponseHTTP{
				Success: false,
				Message: fmt.Sprintf("Channel with ID %v not found.", pc.Id),
				Data:    nil,
			})
		default:
			return c.Status(http.StatusServiceUnavailable).JSON(serialize.ResponseHTTP{
				Success: false,
				Message: err.Error(),
				Data:    nil,
			})

		}
	}

	channelKey := channel.ChannelKey
	groupId := channel.GroupID

	group := new(model.Group)
	db.First(&group, groupId)

	defDict := new(model.DefDict)
	db.First(&defDict, 1)

	tabNameDict := map[string]string{}
	err := json.Unmarshal([]byte(defDict.Dict), &tabNameDict)
	if err != nil {
		panic(err)
	}

	var wg sync.WaitGroup
	wg.Add(1)
	AssemblyServerData(1, *channelKey, *group, tabNameDict, &wg)

	// rdb.Set(context.Background(), *channelKey, jsonData, 50*time.Second)

	//basePath := "E:\\GoCode\\fiber-ci\\static\\server"
	//filePath := fmt.Sprintf("%s\\%s.json", basePath, *channelKey)
	//
	//err = utils.WriteFile(filePath, jsonData)
	//if err != nil {
	//	panic(err)
	//}

	endTime := time.Now()

	// 计算程序执行耗时
	elapsedTime := endTime.Sub(startTime)

	// 转换为秒
	elapsedTimeInSeconds := elapsedTime.Seconds()

	return c.JSON(serialize.ResponseHTTP{
		Success: true,
		Message: "Create all channel json success",
		Data:    elapsedTimeInSeconds,
	})

}

// CreateAllChannelJson is a function to Create channel by ID
// @Summary 生成全部渠道Json文件
// @Description 通过ID=0生成全部渠道Json文件
// @Tags Channel
// @Accept json
// @Produce json
// @Param channel_id body PostChannel true "PostChannel"
// @Success 200 {object} serialize.ResponseHTTP{}
// @Failure 404 {object} serialize.ResponseHTTP{}
// @Failure 503 {object} serialize.ResponseHTTP{}
// @Router /v1/channel/createalljson [post]
func CreateAllChannelJson(c *fiber.Ctx) error {
	// 617 kw669hy_android_wei4
	startTime := time.Now()
	db := database.DB
	pc := new(PostChannel)
	if err := c.BodyParser(&pc); err != nil {
		return c.Status(http.StatusBadRequest).JSON(serialize.ResponseHTTP{
			Success: false,
			Message: err.Error(),
			Data:    nil,
		})
	}
	if pc.Id != 0 {
		return c.JSON(serialize.ResponseHTTP{
			Success: true,
			Message: "生成全部渠道Json文件失败, error:id部不为0",
			Data:    "error",
		})
	} else {
		var wg sync.WaitGroup
		var channels []model.Channel
		result := db.Find(&channels)
		if result.Error != nil {
			panic(result.Error)
		}
		for i, channel := range channels {
			index := i + 1
			wg.Add(1)
			channelKey := channel.ChannelKey
			groupId := channel.GroupID

			group := new(model.Group)
			db.First(&group, groupId)

			defDict := new(model.DefDict)
			db.First(&defDict, 1)

			tabNameDict := map[string]string{}
			err := json.Unmarshal([]byte(defDict.Dict), &tabNameDict)
			if err != nil {
				panic(err)
			}

			go func() {
				AssemblyServerData(index, *channelKey, *group, tabNameDict, &wg)
			}()
		}
		wg.Wait()

		endTime := time.Now()

		// 计算程序执行耗时
		elapsedTime := endTime.Sub(startTime)

		// 转换为秒
		elapsedTimeInSeconds := elapsedTime.Seconds()

		return c.JSON(serialize.ResponseHTTP{
			Success: true,
			Message: "Create all channel json success",
			Data:    elapsedTimeInSeconds,
		})

	}

}
